package velox.jcr.mapper.declarative;

import java.beans.PropertyDescriptor;
import java.util.Calendar;
import java.util.Map;

import javax.jcr.Node;
import javax.jcr.RepositoryException;

import org.springframework.beans.BeanWrapper;

public class BasicMapping implements Mapping {

	private String javaProperty;
	private String jcrProperty;

	public BasicMapping(String javaProperty, String jcrProperty) {
		this.javaProperty = javaProperty;
		this.jcrProperty = jcrProperty;
	}

	public void read(Node node, BeanWrapper destination) throws RepositoryException {
		PropertyDescriptor desc = destination.getPropertyDescriptor(javaProperty);
		if (Calendar.class.isAssignableFrom(desc.getPropertyType())) {
			destination.setPropertyValue(javaProperty, node.getProperty(jcrProperty).getDate());
		} else {
			destination.setPropertyValue(javaProperty, node.getProperty(jcrProperty).getString());
		}
	}

	public void readFromCache(Map<String, Object> cache, BeanWrapper destination) {
		destination.setPropertyValue(javaProperty, cache.get(jcrProperty));
	}

	public String getJavaProperty() {
		return javaProperty;
	}
	
	// TODO: Support pluggable converters
	public void write(Node node, BeanWrapper object, boolean create) throws RepositoryException {
		Object o = object.getPropertyValue(javaProperty);
		if (o instanceof String) {
			node.setProperty(jcrProperty, (String) o);
		} else if (o instanceof Integer) {
			node.setProperty(jcrProperty, (Integer) o);
		} else if (o instanceof Long) {
			node.setProperty(jcrProperty, (Long) o);
		} else if (o instanceof Float) {
			node.setProperty(jcrProperty, (Float) o);
		} else if (o instanceof Double) {
			node.setProperty(jcrProperty, (Double) o);
		} else if (o instanceof Calendar) {
			node.setProperty(jcrProperty, (Calendar) o);
		} else {
			throw new IllegalArgumentException("Cannot write properties of type " + o.getClass());
		}
	}

	public void writeToCache(Map<String, Object> cache, BeanWrapper object) {
		cache.put(jcrProperty, object.getPropertyValue(javaProperty));
	}

}
